package screen;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.io.HttpConnection;

import net.rim.device.api.io.IOUtilities;
import net.rim.device.api.io.transport.ConnectionDescriptor;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.Characters;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.FontFamily;
import net.rim.device.api.ui.FontManager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.menu.SubMenu;
import net.rim.device.api.util.StringProvider;

import org.json.me.JSONException;
import org.json.me.JSONObject;

import weibo.Oauth;
import weibo.http.AccessToken;
import weibo.model.Comment;
import weibo.model.CommentWapper;
import weibo.model.Status;
import weibo.model.StatusWapper;
import weibo.model.WeiboException;
import code.Config;
import code.Function;
import ctrl.ForegroundManager;
import ctrl.ListStyleButtonSet;
import ctrl.MyConnectionFactory;
import ctrl.StatusesListStyleButtonField;
import ctrl.UserInforListStyleButtonField;

public final class WeiboScreen extends MainScreen
{
	private AccessToken accessToken;
	
	private ForegroundManager _foreground=new ForegroundManager(0);
	private ListStyleButtonSet _buttonSet=new ListStyleButtonSet();
	private StatusesListStyleButtonField _link;
	
	private int currentStatusType=0;
	private int currentCommentType=0;
	private int currentPage=-1;
	
	private DownloadImageThread _imageThread=new DownloadImageThread();
	
    public WeiboScreen(AccessToken oauth2AccessToken) throws WeiboException
    {
    	super(NO_VERTICAL_SCROLL | USE_ALL_HEIGHT | NO_SYSTEM_MENU_ITEMS);
    	setTitle(Config.APP_TITLE);
        
    	Font _appFont;
    	try {
			FontFamily family=FontFamily.forName("BBGlobal Sans");
			_appFont=family.getFont(Font.PLAIN, 7, Ui.UNITS_pt);
			FontManager.getInstance().setApplicationFont(_appFont);
		} catch (ClassNotFoundException e) {e.printStackTrace();}

    	accessToken=oauth2AccessToken;
    	setTitle(Config.APP_TITLE + " - " + accessToken.getUID());

    	_buttonSet.add(new LabelField(" ", USE_ALL_WIDTH));
		_foreground.add(_buttonSet);
		add(_foreground);

		UiApplication.getUiApplication().invokeLater(new Runnable()
		{
			public void run() {refreshStatus();}
		});
    }
    
    
    
    private MenuItem menuNewStatus=new MenuItem(new StringProvider("发表微博"), 1, 10)
    {
    	public void run()
    	{
    		UiApplication.getUiApplication().pushScreen(new NewStatusScreen(accessToken));
    	}
    };
    
    private MenuItem menuMyStatuses=new MenuItem(new StringProvider("我的微博"), 5, 10)
    {
    	public void run()
    	{
    		UiApplication.getUiApplication().pushScreen(new ShowStatusesScreen(accessToken));
    	}
    };
    
    private MenuItem menuRefreshStatus=new MenuItem(new StringProvider("刷新微博"), 10, 10)
    {
    	public void run() {refreshStatus();}
    };
    
    private MenuItem menuMyFollowedStatus=new MenuItem(new StringProvider("\u221A我关注的最新微博"), 10, 10)
    {
    	public void run()
    	{
    		currentStatusType=Config.STATUS_TYPE_FRIENDSTIMELINE;
    		menuMyFollowedStatus.setText(new StringProvider("\u221A我关注的最新微博"));
    		menuPublicStatus.setText(new StringProvider("最新的公共微博"));
    		refreshStatus();
    	}
    };

    private MenuItem menuPublicStatus=new MenuItem(new StringProvider("最新的公共微博"), 20, 10)
    {
    	public void run()
    	{
    		currentStatusType=Config.STATUS_TYPE_PUBLICTIMELINES;
    		menuPublicStatus.setText(new StringProvider("\u221A最新的公共微博"));
    		menuMyFollowedStatus.setText(new StringProvider("我关注的最新微博"));
    		refreshStatus();
    	}
    };
    
    private MenuItem menuCommentsMentions=new MenuItem(new StringProvider("@我的微博"), 10, 10)
    {
    	public void run()
    	{
    		currentCommentType=Config.COMMENT_TYPE_MENTIONS;
    		refreshComments();
    	}
    };

    private MenuItem menuCommentsToMe=new MenuItem(new StringProvider("我收到的评论"), 20, 10)
    {
    	public void run()
    	{
    		currentCommentType=Config.COMMENT_TYPE_TOME;
    		refreshComments();
    	}
    };

    private MenuItem menuCommentsByMe=new MenuItem(new StringProvider("我发出的评论"), 30, 10)
    {
    	public void run()
    	{
    		currentCommentType=Config.COMMENT_TYPE_BYME;
    		refreshComments();
    	}
    };

    private MenuItem menuUserInformation=new MenuItem(new StringProvider("个人信息"), 40, 10)
    {
    	public void run()
    	{
    		UiApplication.getUiApplication().invokeLater(new Runnable()
    		{
				public void run()
				{
		    		UiApplication.getUiApplication().pushScreen(new UserInformationScreen(accessToken));					
				}
			});
    	}
    };
    
    private MenuItem menuUserLogout=new MenuItem(new StringProvider("注销用户"), 40, 20)
    {
    	public void run()
    	{
    		Oauth oauth=new Oauth(accessToken.getToken());
    		try {
				JSONObject logout=oauth.revoke();
				
				if(logout.get("result").equals("true"))
				{
					Dialog.alert("用户已退出登录，要继续使用请重新登录！");
					
					System.exit(0);
				}
			} catch (WeiboException e) {Function.errorDialog(e.toString());}
    		  catch (JSONException e2) {Function.errorDialog(e2.toString());}
    	}
    };
    
    private MenuItem menuAbout=new MenuItem(new StringProvider("帮助和关于"), 50, 10)
    {
    	public void run() {UiApplication.getUiApplication().pushScreen(new AboutScreen());}
    };

    protected void makeMenu(Menu menu, int instance) 
    {
    	SubMenu menuStatusType=new SubMenu(null, "查看微博", 20, 10);
    	menuStatusType.add(menuMyFollowedStatus);
    	menuStatusType.add(menuPublicStatus);
    	
    	SubMenu menuCommentsType=new SubMenu(null, "查看信息", 30, 10);
    	menuCommentsType.add(menuCommentsMentions);
    	menuCommentsType.add(menuCommentsToMe);
    	menuCommentsType.add(menuCommentsByMe);
    	
    	menu.add(menuNewStatus);
    	menu.addSeparator();
    	menu.add(menuMyStatuses);
    	menu.add(menuRefreshStatus);
    	menu.add(menuStatusType);
    	menu.addSeparator();
    	menu.add(menuCommentsType);
    	menu.addSeparator();
    	menu.add(menuUserInformation);
    	menu.addSeparator();
    	menu.add(menuUserLogout);
    	menu.addSeparator();
    	menu.add(menuAbout);
    }
    
    protected boolean keyChar(char key, int status, int time)
    {
    	if(key==Characters.LATIN_CAPITAL_LETTER_P || key==Characters.LATIN_SMALL_LETTER_P)
    	{
    		Function.errorDialog("Active threads: " + (Thread.activeCount()-1) + "\nCurrent page: " + currentPage);
    		return true;
    	}
    	
    	return super.keyChar(key, status, time);
    }
    
    public boolean onClose()
    {
    	_imageThread.stop();
    	
    	return super.onClose();
    }

    private void prepareImageThread()
    {
		_imageThread.stop();
		_imageThread=new DownloadImageThread();
		_imageThread.start();
    }
    
    private void deleteLoadMoreList()
    {
    	Field child=_buttonSet.getField(_buttonSet.getFieldCount()-1);
		if(child instanceof UserInforListStyleButtonField)
		{
			_buttonSet.delete(child);
		}	
    }
    
    private void refreshStatus()
    {
    	currentPage=1;
    	prepareImageThread();
    	
		Application.getApplication().invokeLater(new LoadMoreStatuses());
    }
    
    private void refreshComments()
    {
    	currentPage=1;
    	prepareImageThread();
    	
    	Application.getApplication().invokeLater(new LoadMoreComments());
    }
    
    private void displayStatuses(StatusWapper statuses)
    {
    	Status status;
		for(int i=0; i<statuses.getStatuses().size(); i++)
		{
			status=(Status) statuses.getStatuses().elementAt(i);

			_link=new StatusesListStyleButtonField(status);
			final Status currentStatus=status;
			_link.setChangeListener(new FieldChangeListener()
			{
				public void fieldChanged(Field field, int context)
				{
					UiApplication.getUiApplication().pushScreen(new ShowStatusScreen(accessToken, currentStatus));
				}
			});

			_buttonSet.add(_link);
		}
		
		if(currentStatusType==Config.STATUS_TYPE_FRIENDSTIMELINE)
		{
    		UserInforListStyleButtonField _loadMore=new UserInforListStyleButtonField("加载更多内容", null, null);
			_loadMore.setChangeListener(new FieldChangeListener()
			{
				public void fieldChanged(Field field, int context)
				{
					deleteLoadMoreList();
					currentPage+=1;
					prepareImageThread();
					
					Application.getApplication().invokeLater(new LoadMoreStatuses());
				}
			});
			_buttonSet.add(_loadMore);
		}
		
		_imageThread.fetch(statuses);
	}	

    private void displayComments(CommentWapper comments)
    {
    	Comment comment;
		for(int i=0; i<comments.getComments().size(); i++)
		{
			comment=(Comment) comments.getComments().elementAt(i);
			_link=new StatusesListStyleButtonField(comment);
			_buttonSet.add(_link);
		}
		
		UserInforListStyleButtonField _loadMore=new UserInforListStyleButtonField("加载更多内容", null, null);
		_loadMore.setChangeListener(new FieldChangeListener()
		{
			public void fieldChanged(Field field, int context)
			{
				deleteLoadMoreList();
				currentPage+=1;
				prepareImageThread();
				
				Application.getApplication().invokeLater(new LoadMoreComments());
			}
		});
		_buttonSet.add(_loadMore);
		
		_imageThread.fetch(comments);
	}	
    
    private class LoadMoreStatuses implements Runnable
    {
		public void run()
		{
			StatusWapper statuses;
			RefreshStatusesScreen popupScreen=new RefreshStatusesScreen(accessToken, currentPage, currentStatusType);
			UiApplication.getUiApplication().pushModalScreen(popupScreen);
			
			statuses=popupScreen.getStatuses();
			if(popupScreen!=null) {popupScreen=null;}
			if(statuses!=null)
			{
				if(_buttonSet.getFieldCount()>0 && currentPage==1) {_buttonSet.deleteAll();}
				displayStatuses(statuses);
			}
		}
	}
    
    private class LoadMoreComments implements Runnable
    {
		public void run()
		{
			CommentWapper comments;
			RefreshCommentsScreen popupScreen=new RefreshCommentsScreen(accessToken, currentPage, currentCommentType);
			UiApplication.getUiApplication().pushModalScreen(popupScreen);
			
			comments=popupScreen.getComments();
			if(popupScreen!=null) {popupScreen=null;}
			if(comments!=null)
			{
				if(_buttonSet.getFieldCount()>0 && currentPage==1) {_buttonSet.deleteAll();}
				displayComments(comments);
			}
		}
	}
  
	class DownloadImageThread extends Thread
    {
        private static final int TIMEOUT = 500;
        private byte[] data;
        private StatusWapper _statuses=null;
        private CommentWapper _comments=null;
        
        private Status status=null;
        private Comment comment=null;
        private MyConnectionFactory factory=null;
        private ConnectionDescriptor descriptor=null;
        private HttpConnection httpConnection=null;
        private InputStream inputStream=null;

        private volatile boolean _fetchStarted = false;
        private volatile boolean _stop = false;

        private void fetch(StatusWapper statuses)
        {
        	_fetchStarted=true;
        	_statuses=statuses;
        }

        private void fetch(CommentWapper comments)
        {
        	_fetchStarted=true;
        	_comments=comments;
        }
        
        private void stop() {_stop = true;}
        
        private void download(String url, int index, int image_type)
        {
        	descriptor=factory.getConnection(url);
        	
            if(descriptor==null)
            {
            	_fetchStarted=false;
            	stop();
            	return;
            }
            
            httpConnection=(HttpConnection) descriptor.getConnection();
            
            try
            {
				inputStream=httpConnection.openInputStream();
				
				if(inputStream.available()>0)
				{
					data=IOUtilities.streamToBytes(inputStream);

					if(data.length==httpConnection.getLength())
					{
						index=index+currentPage*20-20;
						synchronized(Application.getEventLock())
						{
							try {
								StatusesListStyleButtonField link=(StatusesListStyleButtonField) _buttonSet.getField(index);
								
								switch (image_type)
				                {
									case Config.IMAGE_TYPE_AVATAR: link.setAvatarIcon(data); break;
									case Config.IMAGE_TYPE_STATUS: link.setStatusImage(data); break;
									case Config.IMAGE_TYPE_RETWEET: link.setRetweetImage(data); break;
								}
							} catch (Exception e) {}
						}
					}
				}
            } catch (IOException e) {}
        }

        public void run()
        {
            for(;;)
            {
                while(!_fetchStarted && !_stop)  
                {
                    try {sleep(TIMEOUT);} catch (InterruptedException e) {Function.errorDialog(StatusesListStyleButtonField.class.getName() + "\n\n" + "Thread#sleep threw " + e.toString());}
                }
                
                if(_stop) {return;}

                if(_statuses!=null)
                {
                    for(int i=0; i<_statuses.getStatuses().size(); i++)
                    {
                    	if(_stop) {return;}
                    	
                    	status=(Status) _statuses.getStatuses().elementAt(i);
                    	String avatar=status.getUser().getProfileImageUrl();
                    	String[] image_status=status.getThumbnailImages();
                    	String[] image_retweet = null;
                    	Status retweet=status.getRetweetedStatus();
                    	if(retweet!=null)
                    	{
                    		if(!retweet.isDeleted()) {image_retweet=retweet.getThumbnailImages();}
                    	}
                    	
                        factory=new MyConnectionFactory();
                        
                        download(avatar, i, Config.IMAGE_TYPE_AVATAR);
                        if(image_status!=null) {download(image_status[0], i, Config.IMAGE_TYPE_STATUS);}
                        if(image_retweet!=null) {download(image_retweet[0], i, Config.IMAGE_TYPE_RETWEET);}
                    }
                } else if(_comments!=null)
                {
                	for(int i=0; i<_comments.getComments().size(); i++)
                	{
                		if(_stop) {return;}
                		
                		comment=(Comment) _comments.getComments().elementAt(i);
                		String avatar=comment.getUser().getProfileImageUrl();
                		String[] image_retweet = null;
                		Status retweet=comment.getStatus();
                		if(retweet!=null)
                		{
                			if(!retweet.isDeleted()) {image_retweet=retweet.getThumbnailImages();}
                		}
                		
                		factory=new MyConnectionFactory();
                		
                		download(avatar, i, Config.IMAGE_TYPE_AVATAR);
                		if(image_retweet!=null) {download(image_retweet[0], i, Config.IMAGE_TYPE_RETWEET);}
                	}
                }

                if(inputStream!=null) {try {inputStream.close();} catch (Exception e2) {}}
                if(httpConnection!=null) {try {httpConnection.close();} catch (Exception e2) {}}
                
                _fetchStarted = false;           
                stop();
            }
        }
    }
}